home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / network / manageme / tcpdump-.7 / tcpdump- / tcpdump-richard-1.7 / tcpdump-3.0 / print-bootp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-03  |  8.9 KB  |  359 lines

  1. /*
  2.  * Copyright (c) 1990, 1991, 1993, 1994
  3.  *    The Regents of the University of California.  All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that: (1) source code distributions
  7.  * retain the above copyright notice and this paragraph in its entirety, (2)
  8.  * distributions including binary code include the above copyright notice and
  9.  * this paragraph in its entirety in the documentation or other materials
  10.  * provided with the distribution, and (3) all advertising materials mentioning
  11.  * features or use of this software display the following acknowledgement:
  12.  * ``This product includes software developed by the University of California,
  13.  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
  14.  * the University nor the names of its contributors may be used to endorse
  15.  * or promote products derived from this software without specific prior
  16.  * written permission.
  17.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  18.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  19.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  20.  *
  21.  * Format and print bootp packets.
  22.  */
  23. #ifndef lint
  24. static char rcsid[] =
  25.     "@(#) $Header: print-bootp.c,v 1.30 94/06/14 20:17:37 leres Exp $ (LBL)";
  26. #endif
  27.  
  28. #include <sys/param.h>
  29. #include <sys/time.h>
  30. #include <sys/types.h>
  31. #include <sys/socket.h>
  32.  
  33. #include <net/if.h>
  34.  
  35. #include <netinet/in.h>
  36. #include <netinet/if_ether.h>
  37.  
  38. #include <ctype.h>
  39. #include <string.h>
  40. #include <stdio.h>
  41.  
  42. #include "interface.h"
  43. #include "addrtoname.h"
  44. #include "bootp.h"
  45.  
  46. static void rfc1048_print(const u_char *, int);
  47. static void cmu_print(const u_char *, int);
  48.  
  49. static char tstr[] = " [|bootp]";
  50.  
  51. /*
  52.  * Print bootp requests
  53.  */
  54. void
  55. bootp_print(register const u_char *cp, int length,
  56.         u_short sport, u_short dport)
  57. {
  58.     register const struct bootp *bp;
  59.     static u_char vm_cmu[4] = VM_CMU;
  60.     static u_char vm_rfc1048[4] = VM_RFC1048;
  61.     const u_char *ep;
  62.  
  63. #define TCHECK(var, l) if ((u_char *)&(var) > ep - l) goto trunc
  64.  
  65.     bp = (struct bootp *)cp;
  66.     /* 'ep' points to the end of avaible data. */
  67.     ep = snapend;
  68.  
  69.     TCHECK(bp->bp_op, sizeof(bp->bp_op));
  70.     switch (bp->bp_op) {
  71.  
  72.     case BOOTREQUEST:
  73.         /* Usually, a request goes from a client to a server */
  74.         if (sport != IPPORT_BOOTPC || dport != IPPORT_BOOTPS)
  75.             printf(" (request)");
  76.         break;
  77.  
  78.     case BOOTREPLY:
  79.         /* Usually, a reply goes from a server to a client */
  80.         if (sport != IPPORT_BOOTPS || dport != IPPORT_BOOTPC)
  81.             printf(" (reply)");
  82.         break;
  83.  
  84.     default:
  85.         printf(" bootp-#%d", bp->bp_op);
  86.     }
  87.  
  88.     TCHECK(bp->bp_secs, sizeof(bp->bp_secs));
  89.  
  90.     /* The usual hardware address type is 1 (10Mb Ethernet) */
  91.     if (bp->bp_htype != 1)
  92.         printf(" htype-#%d", bp->bp_htype);
  93.  
  94.     /* The usual length for 10Mb Ethernet address is 6 bytes */
  95.     if (bp->bp_htype != 1 || bp->bp_hlen != 6)
  96.         printf(" hlen:%d", bp->bp_hlen);
  97.  
  98.     /* Only print interesting fields */
  99.     if (bp->bp_hops)
  100.         printf(" hops:%d", bp->bp_hops);
  101.     if (bp->bp_xid)
  102.         printf(" xid:0x%x", ntohl(bp->bp_xid));
  103.     if (bp->bp_secs)
  104.         printf(" secs:%d", ntohs(bp->bp_secs));
  105.  
  106.     /* Client's ip address */
  107.     TCHECK(bp->bp_ciaddr, sizeof(bp->bp_ciaddr));
  108.     if (bp->bp_ciaddr.s_addr)
  109.         printf(" C:%s", ipaddr_string(&bp->bp_ciaddr));
  110.  
  111.     /* 'your' ip address (bootp client) */
  112.     TCHECK(bp->bp_yiaddr, sizeof(bp->bp_yiaddr));
  113.     if (bp->bp_yiaddr.s_addr)
  114.         printf(" Y:%s", ipaddr_string(&bp->bp_yiaddr));
  115.  
  116.     /* Server's ip address */
  117.     TCHECK(bp->bp_siaddr, sizeof(bp->bp_siaddr));
  118.     if (bp->bp_siaddr.s_addr)
  119.         printf(" S:%s", ipaddr_string(&bp->bp_siaddr));
  120.  
  121.     /* Gateway's ip address */
  122.     TCHECK(bp->bp_giaddr, sizeof(bp->bp_giaddr));
  123.     if (bp->bp_giaddr.s_addr)
  124.         printf(" G:%s", ipaddr_string(&bp->bp_giaddr));
  125.  
  126.     /* Client's Ethernet address */
  127.     if (bp->bp_htype == 1 && bp->bp_hlen == 6) {
  128.         register const struct ether_header *eh;
  129.         register const char *e;
  130.  
  131.         TCHECK(bp->bp_chaddr[0], 6);
  132.         eh = (struct ether_header *)packetp;
  133.         if (bp->bp_op == BOOTREQUEST)
  134.             e = (const char *)ESRC(eh);
  135.         else if (bp->bp_op == BOOTREPLY)
  136.             e = (const char *)EDST(eh);
  137.         else
  138.             e = 0;
  139.         if (e == 0 || bcmp((char *)bp->bp_chaddr, e, 6) != 0)
  140.             printf(" ether %s", etheraddr_string(bp->bp_chaddr));
  141.     }
  142.  
  143.     TCHECK(bp->bp_sname[0], 1);        /* check first char only */
  144.     if (*bp->bp_sname) {
  145.         printf(" sname ");
  146.         if (fn_print(bp->bp_sname, ep)) {
  147.             fputs(tstr + 1, stdout);
  148.             return;
  149.         }
  150.     }
  151.     TCHECK(bp->bp_sname[0], 1);        /* check first char only */
  152.     if (*bp->bp_file) {
  153.         printf(" file ");
  154.         if (fn_print(bp->bp_file, ep)) {
  155.             fputs(tstr + 1, stdout);
  156.             return;
  157.         }
  158.     }
  159.  
  160.     /* Decode the vendor buffer */
  161.     TCHECK(bp->bp_vend[0], sizeof(bp->bp_vend));
  162.     length -= sizeof(*bp) - sizeof(bp->bp_vend);
  163.     if (bcmp((char *)bp->bp_vend, (char *)vm_rfc1048,
  164.          sizeof(u_int32)) == 0)
  165.         rfc1048_print(bp->bp_vend, length);
  166.     else if (bcmp((char *)bp->bp_vend, (char *)vm_cmu,
  167.               sizeof(u_int32)) == 0)
  168.         cmu_print(bp->bp_vend, length);
  169.     else {
  170.         u_int32 ul;
  171.  
  172.         bcopy((char *)bp->bp_vend, (char *)&ul, sizeof(ul));
  173.         if (ul != 0)
  174.             printf("vend-#0x%x", ul);
  175.     }
  176.  
  177.     return;
  178. trunc:
  179.     fputs(tstr, stdout);
  180. #undef TCHECK
  181. }
  182.  
  183. /* The first character specifies the format to print */
  184. static struct token tag2str[] = {
  185. /* RFC1048 tags */
  186.     { TAG_PAD,        " PAD" },
  187.     { TAG_SUBNET_MASK,    "iSM" },    /* subnet mask (RFC950) */
  188.     { TAG_TIME_OFFSET,    "lTZ" },    /* seconds from UTC */
  189.     { TAG_GATEWAY,        "iDG" },    /* default gateway */
  190.     { TAG_TIME_SERVER,    "iTS" },    /* time servers (RFC868) */
  191.     { TAG_NAME_SERVER,    "iIEN" },    /* IEN name servers (IEN116) */
  192.     { TAG_DOMAIN_SERVER,    "iNS" },    /* domain name (RFC1035) */
  193.     { TAG_LOG_SERVER,    "iLOG" },    /* MIT log servers */
  194.     { TAG_COOKIE_SERVER,    "iCS" },    /* cookie servers (RFC865) */
  195.     { TAG_LPR_SERVER,    "iLPR" },    /* lpr server (RFC1179) */
  196.     { TAG_IMPRESS_SERVER,    "iIM" },    /* impress servers (Imagen) */
  197.     { TAG_RLP_SERVER,    "iRL" },    /* resource location (RFC887) */
  198.     { TAG_HOSTNAME,        "aHN" },    /* ascii hostname */
  199.     { TAG_BOOTSIZE,        "sBS" },    /* 512 byte blocks */
  200.     { TAG_END,        " END" },
  201. /* RFC1497 tags */
  202.     { TAG_DUMPPATH,        "aDP" },
  203.     { TAG_DOMAINNAME,    "aDN" },
  204.     { TAG_SWAP_SERVER,    "iSS" },
  205.     { TAG_ROOTPATH,        "aRP" },
  206.     { TAG_EXTPATH,        "aEP" },
  207.     { 0,            NULL }
  208. };
  209.  
  210. static void
  211. rfc1048_print(register const u_char *bp, register int length)
  212. {
  213.     register u_char tag;
  214.     register const u_char *ep;
  215.     register u_int len, size;
  216.     register const char *cp;
  217.     register char c;
  218.     int first;
  219.     u_int32 ul;
  220.     u_short us;
  221.  
  222.     printf(" vend-rfc1048");
  223.  
  224.     /* Setup end pointer */
  225.     ep = bp + length;
  226.  
  227.     /* Step over magic cookie */
  228.     bp += sizeof(int32);
  229.  
  230.     /* Loop while we there is a tag left in the buffer */
  231.     while (bp + 1 < ep) {
  232.         tag = *bp++;
  233.         if (tag == TAG_PAD)
  234.             continue;
  235.         if (tag == TAG_END)
  236.             return;
  237.         cp = tok2str(tag2str, "?T%d", tag);
  238.         c = *cp++;
  239.         printf(" %s:", cp);
  240.  
  241.         /* Get the length; check for truncation */
  242.         if (bp + 1 >= ep) {
  243.             fputs(tstr, stdout);
  244.             return;
  245.         }
  246.         len = *bp++;
  247.         if (bp + len >= ep) {
  248.             fputs(tstr, stdout);
  249.             return;
  250.         }
  251.  
  252.         /* Print data */
  253.         size = len;
  254.         if (c == '?') {
  255.             /* Base default formats for unknown tags on data size */
  256.             if (size & 1)
  257.                 c = 'b';
  258.             else if (size & 2)
  259.                 c = 's';
  260.             else
  261.                 c = 'l';
  262.         }
  263.         first = 1;
  264.         switch (c) {
  265.  
  266.         case 'a':
  267.             /* ascii strings */
  268.             (void)fn_printn(bp, size, NULL);
  269.             bp += size;
  270.             size = 0;
  271.             break;
  272.  
  273.         case 'i':
  274.         case 'l':
  275.             /* ip addresses/32-bit words */
  276.             while (size >= sizeof(ul)) {
  277.                 if (!first)
  278.                     putchar(',');
  279.                 bcopy((char *)bp, (char *)&ul, sizeof(ul));
  280.                 if (c == 'i')
  281.                     printf("%s", ipaddr_string(&ul));
  282.                 else
  283.                     printf("%lu", ul);
  284.                 bp += sizeof(ul);
  285.                 size -= sizeof(ul);
  286.                 first = 0;
  287.             }
  288.             break;
  289.  
  290.         case 's':
  291.             /* shorts */
  292.             while (size >= sizeof(us)) {
  293.                 if (!first)
  294.                     putchar(',');
  295.                 bcopy((char *)bp, (char *)&us, sizeof(us));
  296.                 printf("%d", us);
  297.                 bp += sizeof(us);
  298.                 size -= sizeof(us);
  299.                 first = 0;
  300.             }
  301.             break;
  302.  
  303.         case 'b':
  304.         default:
  305.             /* Bytes */
  306.             while (size > 0) {
  307.                 if (!first)
  308.                     putchar('.');
  309.                 printf("%d", *bp);
  310.                 ++bp;
  311.                 --size;
  312.                 first = 0;
  313.             }
  314.             break;
  315.         }
  316.         /* Data left over? */
  317.         if (size)
  318.             printf("[len %d]", len);
  319.     }
  320. }
  321.  
  322. static void
  323. cmu_print(register const u_char *bp, register int length)
  324. {
  325.     register const struct cmu_vend *cmu;
  326.     register const u_char *ep;
  327.     char *fmt = " %s:%s";
  328.  
  329. #define TCHECK(var, l) if ((u_char *)&(var) > ep - l) goto trunc
  330. #define PRINTCMUADDR(m, s) { TCHECK(cmu->m, sizeof(cmu->m)); \
  331.     if (cmu->m.s_addr != 0) \
  332.     printf(fmt, s, ipaddr_string(&cmu->m.s_addr)); }
  333.  
  334.     /* Setup end pointer */
  335.     ep = bp + length;
  336.  
  337.     printf(" vend-cmu");
  338.     cmu = (struct cmu_vend *)bp;
  339.  
  340.     /* Only print if there are unknown bits */
  341.     TCHECK(cmu->v_flags, sizeof(cmu->v_flags));
  342.     if ((cmu->v_flags & ~(VF_SMASK)) != 0)
  343.         printf(" F:0x%x", cmu->v_flags);
  344.     PRINTCMUADDR(v_dgate, "DG");
  345.     PRINTCMUADDR(v_smask, cmu->v_flags & VF_SMASK ? "SM" : "SM*");
  346.     PRINTCMUADDR(v_dns1, "NS1");
  347.     PRINTCMUADDR(v_dns2, "NS2");
  348.     PRINTCMUADDR(v_ins1, "IEN1");
  349.     PRINTCMUADDR(v_ins2, "IEN2");
  350.     PRINTCMUADDR(v_ts1, "TS1");
  351.     PRINTCMUADDR(v_ts2, "TS2");
  352.     return;
  353.  
  354. trunc:
  355.     fputs(tstr, stdout);
  356. #undef TCHECK
  357. #undef PRINTCMUADDR
  358. }
  359.